package com.bank.manage.utils;

import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.TemporalUnit;
import java.util.Date;

/**
 * @author wcl
 * @date 2022/11/10
 */
public class LocalDateTimeUtils {

    /**
     * yyy-MM-dd
     */
    public static final String yyyy_MM_dd = "yyy-MM-dd";
    /**
     * yyyMMdd
     */
    public static final String yyyyMMdd = "yyyMMdd";
    /**
     * yyyy-MM-dd HH:mm:ss
     */
    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    /**
     * yyyyMMddHHmmss
     */
    public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
    /**
     * 转换成 yyyy-MM
     */
    public static final String YYYY_MM = "yyyy-MM";
    /**
     * 转换成yyyy
     */
    public static final String YYYY = "yyyy";

    //Date转换为LocalDateTime
    public static LocalDateTime convertDateToLDT(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    //LocalDateTime转换为Date
    public static Date convertLDTToDate(LocalDateTime time) {
        return Date.from(time.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static LocalDate toLocalDate(LocalDateTime time) {
        return LocalDate.from(time.atZone(ZoneId.systemDefault()).toInstant());
    }


    //获取指定日期的毫秒
    public static Long getMilliByTime(LocalDateTime time) {
        return time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 时间戳转换LocalDateTime
     * @param timeMillis 时间戳
     * @return LocalDateTime
     */
    public static LocalDateTime timestamp2LocalDateTime(long timeMillis ) {
        if (ObjectUtils.isEmpty(timeMillis)) {
            return null;
        }
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timeMillis), ZoneId.systemDefault());
    }

    /**
     * 时间戳转换LocalDate
     * @param timeMillis 时间戳
     * @return LocalDateTime
     */
    public static LocalDate timestamp2LocalDate(long timeMillis ) {
        if (ObjectUtils.isEmpty(timeMillis)) {

            return null;
        }
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timeMillis),ZoneId.systemDefault()).toLocalDate();
    }

    //获取指定日期的秒
    public static Long getSecondsByTime(LocalDateTime time) {
        return time.atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
    }

    //获取指定时间的指定格式
    public static String formatTime(LocalDateTime time,String pattern) {
        return time.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * String转 LocalDate
     *
     * @param dateTimeStr 日期的字符串
     * @param pattern 格式，类似 yyyy-MM-dd
     * @return
     */
    public  static LocalDate toLocalDate(String dateTimeStr, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return LocalDate.parse(dateTimeStr, formatter);
    }
    /**
     * String转 LocalDateTime
     *
     * @param dateTimeStr 日期的字符串
     * @param pattern
     *  格式，类似 yyyy-MM-dd HH:mm:ss
     * @return
     */
    public  static LocalDateTime toLocalDateTime(String dateTimeStr,String pattern) {
        if(StringUtils.isNotBlank(dateTimeStr)){
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
            return LocalDateTime.parse(dateTimeStr, formatter);
        }
        return null;
    }

    /**
     *  localDate 转string
     * @param localDate
     * @param pattern
     * @return
     */
    public static String toString(LocalDate localDate, String pattern){
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern);
        return localDate.format(fmt);
    }

    /**
     *  localDate 转string
     * @param localDateTime
     * @param pattern
     * @return
     */
    public static String toString(LocalDateTime localDateTime, String pattern){
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern);
        return localDateTime.format(fmt);
    }

    //获取当前时间的指定格式
    public static String formatNow(String pattern) {
        return  formatTime(LocalDateTime.now(), pattern);
    }

    //日期加上一个数,根据field不同加不同值,field为ChronoUnit.*
    public static LocalDateTime plus(LocalDateTime time, long number, TemporalUnit field) {
        return time.plus(number, field);
    }

    //日期减去一个数,根据field不同减不同值,field参数为ChronoUnit.*
    public static LocalDateTime minu(LocalDateTime time, long number, TemporalUnit field){
        return time.minus(number,field);
    }

    /**
     * 获取两个日期的差  field参数为ChronoUnit.*
     * @param startTime
     * @param endTime
     * @param field  单位(年月日时分秒)
     * @return
     */
    public static long betweenTwoTime(LocalDateTime startTime, LocalDateTime endTime, ChronoUnit field) {
        Period period = Period.between(LocalDate.from(startTime), LocalDate.from(endTime));
        if (field == ChronoUnit.YEARS) {
            return period.getYears();
        }
        if (field == ChronoUnit.MONTHS) {
            return period.getYears() * 12 + period.getMonths();
        }
        return field.between(startTime, endTime);
    }


    /**
     *获取一天的开始时间，2022,11,10 00:00:00
     */
    public static LocalDateTime getDayStart(LocalDateTime time) {
        return time.withHour(0)
                .withMinute(0)
                .withSecond(0)
                .withNano(0);
    }

    /**
     *获取月的开始时间，2022,11,01 00:00:00
     */
    public static LocalDateTime getMonthStart(LocalDateTime time) {
        return time.withDayOfMonth(1)
                .withHour(0)
                .withMinute(0)
                .withSecond(0)
                .withNano(0);
    }


    /**
     * 获取一天的结束时间，2022,11,10 23:59:59.999999999
     */
    public static LocalDateTime getDayEnd(LocalDateTime time) {
        return time.withHour(23)
                .withMinute(59)
                .withSecond(59);
    }

    /**
     *获取昨天的开始时间，2022,11,10 00:00:00
     */
    public static LocalDateTime getYesterdayStart() {
        return LocalDateTime.now().plusDays(-1)
                .withHour(0)
                .withMinute(0)
                .withSecond(0)
                .withNano(0);
    }
    /**
     *获取昨天的开始时间，2022,11,10 00:00:00
     */
    public static LocalDate getYesterday() {
        return LocalDate.now().plusDays(-1);
    }
    /**
     *获取一天的开始时间，2022,11,10 00:00:00
     */
    public static LocalDateTime getTodayStart() {
        return LocalDateTime.now()
                .withHour(0)
                .withMinute(0)
                .withSecond(0)
                .withNano(0);
    }

    /**
     *获取明天的开始时间 00:00:00
     */
    public static LocalDateTime getTomorrowStart() {
        LocalDateTime time =  LocalDateTime.now().plusDays(1L);
        return time.withHour(0)
                .withMinute(0)
                .withSecond(0)
                .withNano(0);
    }

    /**
     * 获取指定日期的 当天开始时间
     * @param localDate
     * @return
     */
    public static LocalDateTime getThisDayStart(LocalDate localDate){
        return  LocalDateTime.of(
                localDate.getYear(),
                localDate.getMonthValue(),
                localDate.getDayOfMonth(),
                0,0,0
        );
    }
    /**
     * 获取指定日期的 下一天开始时间
     * @param localDate
     * @return
     */
    public static LocalDateTime getNextDayStart(LocalDate localDate){
        LocalDateTime dateTime = LocalDateTime.of(
                localDate.getYear(),
                localDate.getMonthValue(),
                localDate.getDayOfMonth(),
                0,0,0
        );
        return dateTime.plusDays(1);
    }

    /**
     * 获取当前天 加 减 天的 开始时间
     * @param plusDays
     * @return
     */
    public static LocalDateTime getOneDayStart(Long plusDays){
        LocalDateTime todayStart = getTodayStart();
        return todayStart.plusDays(plusDays);
    }


    /**
     * 获取上个月的日期
     * @return
     */
    public static LocalDate getLastMonth() {
        LocalDate now = LocalDate.now();
        LocalDate lastMonthDate = now.plusMonths(-1);
        return lastMonthDate;
    }
    /**
     * 获取指定月的开始时间日期
     * @return
     */
    public static LocalDate getThisMonthStart(LocalDate localDate) {
        LocalDate thisMonth = LocalDate.of(
                localDate.getYear(),
                localDate.getMonthValue(),
                1
        );
        return thisMonth;
    }

    /**
     * 获取指定月的最后一天
     * @param localDate
     * @return
     */
    public static LocalDate getThisMonthEnd(LocalDate localDate) {
        LocalDate lastDay = localDate.with(TemporalAdjusters.lastDayOfMonth());
        LocalDate thisMonth = LocalDate.of(
                localDate.getYear(),
                localDate.getMonthValue(),
                lastDay.getDayOfMonth()
        );
        return thisMonth;
    }

    /**
     * 获取指定月的开始时间日期
     * @return
     */
    public static LocalDate getNextMonthStart(LocalDate localDate) {
        LocalDate thisMonth = LocalDate.of(
                localDate.getYear(),
                localDate.getMonthValue(),
                1
        );
        return thisMonth.plusMonths(1);
    }

    /**
     * 获取当前时间推前num个月的时间 2023-01-12 -> 2022-07-12
     */
    public static LocalDateTime getBeforeMonth(long num) {
        return LocalDateTime.now().plusMonths(-num);
    }

    public static LocalDateTime getFixedMonthStartTime(LocalDate date){
        return LocalDateTime.of(
                date.getYear(),date.getMonthValue(),date.getDayOfMonth(),
                0,0,0
        );
    }

    public static Integer getDaysValue(LocalDate date) {
        Integer repairDay;
        LocalDate currentDay = LocalDate.now();
        Assert.isTrue(!currentDay.isBefore(date), "该方法不能获取未来月份的数据");
        int currentDayYear = currentDay.getYear();
        int currentDayYearMonth = currentDay.getMonthValue();
        int year = date.getYear();
        int monthValue = date.getMonthValue();
        if (currentDayYear == year && currentDayYearMonth == monthValue ) {
            // 是当月 只用修复 当月数据
            repairDay = currentDay.getDayOfMonth();
        } else {
            LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth());
            repairDay = lastDay.getDayOfMonth();
        }
        return repairDay;
    }

    public static boolean dateStrIsValid(String oriDateStr, String pattern) {
        if (StringUtils.isBlank(oriDateStr) || StringUtils.isBlank(pattern)) {
            return false;
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        try {
            Date date = dateFormat.parse(oriDateStr);
            return oriDateStr.equals(dateFormat.format(date));
        } catch (ParseException e) {
            return false;
        }
    }

    /**
     *  比较开始日期字符串 在 结束日期之前
     * @param dateTimeStart 开始日期
     * @param dateTimeEnd 结束日期
     * @return false 开始日期大于结束日期
     */
    public static Boolean isBefore(String dateTimeStart,String dateTimeEnd){
        LocalDate localDateStart = toLocalDate(dateTimeStart, yyyy_MM_dd);
        LocalDate localDateEnd = toLocalDate(dateTimeEnd, yyyy_MM_dd);
        return localDateStart.isBefore(localDateEnd) || localDateStart.isEqual(localDateEnd);
    }

    /**
     * 获取当前年月日
     *
     * @return
     */
    public static String getCurrentDate() {
        LocalDate localDate = LocalDate.now();
        DateTimeFormatter df = DateTimeFormatter.ofPattern(yyyy_MM_dd);
        return df.format(localDate);
    }


    /**
     * 获取当前年月日
     *
     * @return
     */
    public static String getCurrentDateTime() {
        LocalDateTime localDateTime = LocalDateTime.now();
        DateTimeFormatter df = DateTimeFormatter.ofPattern(YYYYMMDDHHMMSS);
        return df.format(localDateTime);
    }
    /**
     *  比较两个日期相差天数
     * @param start
     * @param end
     * @return
     */
    public static Long between(LocalDate start,LocalDate end){
        Long until = start.until(end, ChronoUnit.DAYS);
       return until;
    }
}
